package tech.yozo.bamboo.ui.home;

import android.content.ContentResolver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.material.snackbar.Snackbar;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import nl.siegmann.epublib.domain.Book;
import nl.siegmann.epublib.domain.Resource;
import nl.siegmann.epublib.epub.EpubReader;
import tech.yozo.bamboo.R;
import tech.yozo.bamboo.databinding.FragmentHomeBinding;
import tech.yozo.bamboo.databinding.ItemTransformBinding;
import tech.yozo.bamboo.model.Ebook;
import tech.yozo.bamboo.ui.reading.ReadingViewModel;
import tech.yozo.bamboo.utils.MimeType;

/**
 * Fragment that demonstrates a responsive layout pattern where the format of the content
 * transforms depending on the size of the screen. Specifically this Fragment shows items in
 * the [RecyclerView] using LinearLayoutManager in a small screen
 * and shows items using GridLayoutManager in a large screen.
 */
public class HomeFragment extends Fragment {

    private HomeViewModel model;
    private FragmentHomeBinding binding;

    private final ActivityResultLauncher<String[]> mGetContent =
            registerForActivityResult(new ActivityResultContracts.OpenDocument(), this::getContent);

    private final ActivityResultLauncher<String[]> mGetContents =
            registerForActivityResult(new ActivityResultContracts.OpenMultipleDocuments(), this::getContents);

    private final ActivityResultLauncher<Uri> mTakePicture =
            registerForActivityResult(new ActivityResultContracts.TakePicture(), this::getImage);

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        model = new ViewModelProvider(this).get(HomeViewModel.class);
        model.init(requireContext());

        binding = FragmentHomeBinding.inflate(inflater, container, false);
        View root = binding.getRoot();

        binding.cameraButton.setOnClickListener(this::onCameraButtonClick);
        binding.contentButton.setOnClickListener(this::onContentButtonClick);
        binding.exportBooks.setOnClickListener(this::onExportBooksClick);

        RecyclerView recyclerView = binding.booksView;
        ListAdapter<Ebook, BookViewHolder> adapter = new BooksAdapter(requireActivity());
        recyclerView.setAdapter(adapter);
        model.getBooks().observe(getViewLifecycleOwner(), adapter::submitList);

        // 获取书籍列表
        model.loadBooks();

        return root;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }

    public void onCameraButtonClick(View v) {
        // TODO 调用自研相机
        //NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment_content_main);
        //navController.navigate(R.id.action_to_capture);

        // 调用系统相机
        File file = new File(requireActivity().getCacheDir(), "temp.png");
        Uri imageUri = FileProvider.getUriForFile(requireContext(), requireContext().getPackageName() + ".provider", file);
        mTakePicture.launch(imageUri);
    }

    private void getImage(boolean success) {
        if (success) {
            // OCR识别
            ReadingViewModel model = new ViewModelProvider(requireActivity()).get(ReadingViewModel.class);
            File file = new File(requireActivity().getCacheDir(), "temp.png");
            model.doOCR(BitmapFactory.decodeFile(file.getAbsolutePath()));

            // 先跳转到识别页面
            Bundle bundle = new Bundle();
            bundle.putString("type", MimeType.MIME_TYPE_PNG);
            NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment_content_main);
            navController.navigate(R.id.action_to_reading, bundle);
        }
    }

    /**
     * 选择支持的文件
     *
     * @param v 选择按钮
     */
    public void onContentButtonClick(View v) {
        String[] types = new String[]{
                MimeType.MIME_TYPE_PNG,
                MimeType.MIME_TYPE_JPG,
                MimeType.MIME_TYPE_EPUB
        };
        mGetContent.launch(types);
    }

    private void getContent(Uri uri) {
        if (uri != null) {
            FragmentActivity activity = requireActivity();
            ReadingViewModel model = new ViewModelProvider(activity).get(ReadingViewModel.class);

            ContentResolver resolver = activity.getContentResolver();
            String type = resolver.getType(uri);
            switch (Objects.requireNonNull(type)) {
                case MimeType.MIME_TYPE_PNG:
                case MimeType.MIME_TYPE_JPG:
                case MimeType.MIME_TYPE_EPUB:
                    try {
                        model.doRead(resolver.openInputStream(uri), type);

                        Bundle bundle = new Bundle();
                        bundle.putString("type", type);
                        NavController navController = Navigation.findNavController(activity, R.id.nav_host_fragment_content_main);
                        navController.navigate(R.id.action_to_reading, bundle);
                    } catch (FileNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                    break;
                default:
                    Snackbar.make(binding.contentButton, "不支持的文件类型！", Snackbar.LENGTH_LONG).show();
            }
        }
    }

    private void onExportBooksClick(View view) {
        String[] types = new String[]{
                MimeType.MIME_TYPE_EPUB
        };
        mGetContents.launch(types);
    }

    private void getContents(List<Uri> uris) {
        if (uris != null) {
            FragmentActivity activity = requireActivity();
            ContentResolver resolver = activity.getContentResolver();
            EpubReader reader = new EpubReader();
            List<Ebook> ebooks = new ArrayList<>(uris.size());
            for (Uri uri : uris) {
                String type = resolver.getType(uri);
                switch (Objects.requireNonNull(type)) {
                    case MimeType.MIME_TYPE_EPUB:
                        try {
                            InputStream inputStream = resolver.openInputStream(uri);
                            assert inputStream != null;
                            Book book = reader.readEpub(inputStream);
                            inputStream.close();

                            String fileName = book.getTitle() + ".epub";
                            File file = new File(activity.getFilesDir(), fileName);

                            // 再次打开流，用于保存文件
                            inputStream = resolver.openInputStream(uri);
                            assert inputStream != null;
                            String hash = saveFile(file, inputStream);

                            // 保存封面图片
                            Resource image = book.getCoverImage();
                            String imageName = book.getTitle() + ".jpg";
                            File coverImage = new File(activity.getFilesDir(), imageName);
                            saveFile(coverImage, image.getInputStream());

                            // 创建 Ebook 对象
                            Ebook ebook = new Ebook(book.getTitle(),
                                    fileName,
                                    type,
                                    book.getMetadata().getLanguage(),
                                    imageName,
                                    hash,
                                    0);
                            ebooks.add(ebook);
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                        break;
                }
            }
            // 保存书籍
            model.saveBooks(ebooks);
            // 重新加载书籍列表
            model.loadBooks();
        }
    }

    private String saveFile(File file, InputStream inputStream) {
        MessageDigest digest;
        FileOutputStream outputStream;
        try {
            digest = MessageDigest.getInstance("SHA-256");
            outputStream = new FileOutputStream(file);
            byte[] buffer = new byte[4096];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, length);
                digest.update(buffer, 0, length);
            }
            outputStream.flush();
            outputStream.close();
            inputStream.close();
        } catch (IOException | NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }

        StringBuilder builder = new StringBuilder();
        for(byte b : digest.digest()) {
            builder.append(String.format("%02x", b));
        }
        return file.getName();
    }

    private static class BooksAdapter extends ListAdapter<Ebook, BookViewHolder> {
        private final FragmentActivity activity;

        protected BooksAdapter(FragmentActivity activity) {
            super(new DiffUtil.ItemCallback<>() {
                @Override
                public boolean areItemsTheSame(@NonNull Ebook oldItem, @NonNull Ebook newItem) {
                    return oldItem.hash.equals(newItem.hash);
                }

                @Override
                public boolean areContentsTheSame(@NonNull Ebook oldItem, @NonNull Ebook newItem) {
                    return oldItem.hash.equals(newItem.hash);
                }
            });

            this.activity = activity;
        }

        @NonNull
        @Override
        public BookViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            ItemTransformBinding binding = ItemTransformBinding.inflate(LayoutInflater.from(parent.getContext()));
            return new BookViewHolder(binding);
        }

        @Override
        public void onBindViewHolder(@NonNull BookViewHolder holder, int position) {
            Ebook ebook = getItem(position);
            holder.textView.setText(ebook.title);

            try {
                FileInputStream inputStream = new FileInputStream(new File(activity.getFilesDir(), ebook.coverImage));
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                inputStream.close();
                holder.imageView.setImageBitmap(bitmap);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            holder.imageView.setOnClickListener(v -> {
                String file = getItem(holder.getBindingAdapterPosition()).file;
                String type = getItem(holder.getBindingAdapterPosition()).format;

                ReadingViewModel model = new ViewModelProvider(activity).get(ReadingViewModel.class);
                try {
                    // 电子书加载
                    FileInputStream inputStream = new FileInputStream(new File(activity.getFilesDir(), file));
                    model.doRead(inputStream, type);

                    Bundle bundle = new Bundle();
                    bundle.putString("type", MimeType.MIME_TYPE_EPUB);
                    NavController navController = Navigation.findNavController(activity, R.id.nav_host_fragment_content_main);
                    navController.navigate(R.id.action_to_reading, bundle);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
        }
    }

    private static class BookViewHolder extends RecyclerView.ViewHolder {

        private final ImageView imageView;
        private final TextView textView;

        public BookViewHolder(ItemTransformBinding binding) {
            super(binding.getRoot());
            imageView = binding.imageViewItemTransform;
            textView = binding.textViewItemTransform;
        }
    }
}